#include <iostream>
#include <signal.h>
#include <unistd.h> // getpid

#include <sys/types.h>
#include <sys/wait.h>

// 这样就不用让父进程等待子进程退出，可以干自己的事情

// 但是如果多个子进程同时退出，同时向父进程发送SIGCHLD信号，pindeng位图只会记录一个。所以要写成死循环模式
void notice(int signo)
{
    std::cout << "get a signal: " << signo << "pid: " << getpid() << std::endl;

    while (true)
    {
        pid_t rid = waitpid(-1, nullptr, WNOHANG); // -1等待任意子进程退出
        // WNOHANG 非阻塞方式，防止一部分进程退出，另一部分不退出导致出现一直等待的现象（阻塞）

        if (rid > 0)
        {
            std::cout << "wait child success, rid: " << rid << std::endl;
        }
        else if (rid < 0) // 没有子进程退出了， 就等待失败，退出
        {
            std::cout << "wait child success done " << std::endl;
            break;
        }
        else // 局部等待完成，也退出 WNOHANG
        {
            std::cout << "wait child success done " << std::endl;
            break;
        }
    }
}

void DoOtherThing()
{
    std::cout << "DoOtherTing~" << std::endl;
}

int main()
{

    signal(SIGCHLD, notice);
    pid_t id = fork();
    if (id == 0)
    {
        std::cout << "I am child process, pid: " << getpid() << std::endl;
        sleep(3);
        exit(1);
    }

    while (true)
    {
        DoOtherThing();
        sleep(2);
    }

    return 0;
}

// 在Linux环境中也可以让sigaction 将 SIGCHLD 改成 SIG_IGN，这样就不必等待子进程退出也不会通知父进程了
int main()
{
    signal(SIGCHLD, SIG_IGN); // 设置对SIGCHLD进行忽略即可
    pid_t id = fork();

    if (id == 0)
    {
        int cnt = 5;

        while (cnt--)
        {
            std::cout << "child running" << std::endl;
            sleep(1);
        }

        exit(1);
    }

    while (true)
    {
        std::cout << "father running" << std::endl;
    }

    return 0;
}